﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using AncientEmpires_025_132.ResourceString;
using ShareContent;

namespace AncientEmpires_025_132
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        // Current state of the game
        public enum GameState
        { 
            Menu,
            Play,
        }

        // Current state of Menu
        public enum MenuType
        { 
            MainMenu,
            PlayMenu,
            SkirmishMenu,
            SettingMenu
        }
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        #region Khai báo các biến cần cho game ở đây
        MyMouse myMouse;
        //MainMenu menu;
        MainMenu mainMenu;
        PlayMenu playMenu;
        SkirmishMenu skirmishMenu;
        SettingMenu settingMenu;
        SelectMapMenu selectMapMenu;
        PlayingMenu playingMenu;
        Menu currentMenu;
        GameState gameState;
        GameSettingSetup gameSettingSetup;

        Battle battleGame;
        #endregion


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //this.IsMouseVisible = true;
            InitGraphicsMode(1024, 600, false);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
            
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            gameState = GameState.Menu;
            mainMenu = new MainMenu(Window, Content, GraphicsDevice,"XML/MainMenuWithXML");
            playMenu = new PlayMenu(Window, Content, GraphicsDevice, "XML/PlayMenuWithXML");
            settingMenu = new SettingMenu(Window, Content, GraphicsDevice, "XML/SettingMenuWithXML");
            selectMapMenu = new SelectMapMenu(Content, GraphicsDevice, "XML/SelectMapMenuWithXML", "XML/ListMap");
            currentMenu = mainMenu;
            gameSettingSetup = new GameSettingSetup();
            

            // New delegate
            mainMenu.MenuSelect += new MainMenu.EventHandleMenuSelect(MainMenuSelect);
            playMenu.MenuSelect += new PlayMenu.EventHandleMenuSelect(PlayMenuSelect);
            settingMenu.MenuSelect += new SettingMenu.EventHandleMenuSelect(SettingMenuSelect);
            selectMapMenu.MenuSelect += new SelectMapMenu.EventHandleMenuSelect(SelectMapMenuSelect);
            selectMapMenu.MapSelect += new SelectMapMenu.EventHandleMapSelect(SelectMap);

            InfoMyMouse infomouse = Content.Load<InfoMyMouse>(StringGame.MyMouseStringXML);
            myMouse = new MyMouse(Content, infomouse.ListStrTexture.ToArray(), infomouse.MouseSize);

            MyFont.FontCourierNew = Content.Load<SpriteFont>(StringGame.StringSpriteFont);
            MyFont.FontSegoePrint = Content.Load<SpriteFont>(StringGame.StringXMLSegoePrintFont);
            battleGame = new Battle(Content, Window, StringGame.StringListMap);
            battleGame.MState = myMouse;
            battleGame.EventBackMainMenu += new Battle.EventHandleBackMainMenu(EventBackMainMenu);
            battleGame.EventExitGame += new Battle.EventHandleExitGame(EventExitGame);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            myMouse.Update(gameTime);
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            switch (gameState)
            {
                
                case GameState.Menu:
                    #region old proccess
                    /*
                    switch (menuType)
                    { 
                        case MenuType.MainMenu:
                            
                            MainMenu.Choice mainChoice = mainMenu.GetCurrentChoice();
                            switch (mainChoice)
                            { 
                                case MainMenu.Choice.ChoicePlay:
                                    currentMenu = playMenu;
                                    menuType = MenuType.PlayMenu;
                                break;
                                case MainMenu.Choice.ChoiceSetting:
                                    currentMenu = settingMenu;
                                    menuType = MenuType.SettingMenu;
                                break;
                            }
                            break;
                        case MenuType.PlayMenu:
                            PlayMenu.Choice playChoice = playMenu.GetCurrentChoice();
                            if (playChoice == PlayMenu.Choice.ChoiceBack)
                            {
                                currentMenu = mainMenu;
                                menuType = MenuType.MainMenu;
                            }
                            else if (playChoice == PlayMenu.Choice.ChoiceSkirmish)
                            {
                                currentMenu = skirmishMenu;
                                menuType = MenuType.SkirmishMenu;
                            }
                            break;
                        case MenuType.SkirmishMenu:
                            SkirmishMenu.Choice skirmishChoice = skirmishMenu.GetCurrentChoice();
                            if (skirmishChoice == SkirmishMenu.Choice.ChoiceBack)
                            {
                                currentMenu = playMenu;
                                menuType = MenuType.PlayMenu;
                            }
                            else
                            {
                                if (skirmishChoice == SkirmishMenu.Choice.ChoicePlay)
                                {
                                    gameState = GameState.Play;
                                    battleGame.NewSkirmishGame(Content, Window, "Crossroads", skirmishMenu.SkirmishSetup);
                                }
                            }
                            break;
                        case MenuType.SettingMenu:
                            
                            SettingMenu.Choice settingChoice = settingMenu.GetCurrentChoice();
                            if (settingChoice == SettingMenu.Choice.ChoiceBack)
                            {
                                currentMenu = mainMenu;
                                menuType = MenuType.MainMenu;
                            }
                            else if (settingChoice == SettingMenu.Choice.ChoiceApply)
                            {
                                 //Get new game setting
                                GameSettingSetup newGameSettingSetup = settingMenu.GameSettingSetup;
                                 //Check if any change
                                Boolean isNotChange = gameSettingSetup.Equals(newGameSettingSetup);

                                if (!isNotChange)
                                {
                                     //Proccess when has changes
                                     //Proccess for screen resolution
                                    bool isNotChangeScreenResolution = gameSettingSetup.ScreenResolution.Equals(newGameSettingSetup.ScreenResolution);
                                     //Proccess for is full screen
                                    bool isNotChangeFullScreen = gameSettingSetup.IsFullScreen.Equals(newGameSettingSetup.IsFullScreen);
                                     //Proccess when screen resolution change or is full screen is change
                                    if (!isNotChangeScreenResolution || !isNotChangeFullScreen)
                                    {
                                        switch (newGameSettingSetup.ScreenResolution)
                                        {
                                            case ScreenResolution.sr1024x600:
                                                InitGraphicsMode(1024, 600, newGameSettingSetup.IsFullScreen);
                                                break;
                                            case ScreenResolution.sr1366x768:
                                                InitGraphicsMode(1366, 768, newGameSettingSetup.IsFullScreen);
                                                break;
                                            case ScreenResolution.sr800x600:
                                                InitGraphicsMode(800, 600, newGameSettingSetup.IsFullScreen);
                                                break;
                                        }
                                    }
                                    
                                     //Set old setting equal with new setting
                                    gameSettingSetup = newGameSettingSetup;
                                }
                                else
                                { 
                                     //Proccess if no changes
                                }
                            }
                            
                            break;
                    }
                     */
                    #endregion
                    currentMenu.Update(gameTime);
                    break;
                case GameState.Play:
                    battleGame.Update(gameTime);
                    break;
            }
            
            //////map.Update(gameTime);
            // TODO: Add your update logic here
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            
            GraphicsDevice.Clear(Color.CornflowerBlue);
            
            spriteBatch.Begin();
            switch (gameState)
            {
                case GameState.Play:
                    battleGame.Draw(gameTime, spriteBatch);
                    break;
                case GameState.Menu:
                    currentMenu.Draw(gameTime, spriteBatch);
                    break;
            }
            myMouse.Draw(gameTime, spriteBatch);
            /////map.Draw(gameTime, spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        }

        // Call when main menu select event
        public void MainMenuSelect(int choice)
        {
            switch (choice)
            { 
                case 0:
                    currentMenu = playMenu;
                    break;
                case 1:
                    currentMenu = settingMenu;
                    break;
                case 3:
                    Exit();
                    break;
            }
        }

        // Call when play menu select event
        public void PlayMenuSelect(int choice)
        {
            switch (choice)
            {
                case 2:
                    currentMenu = selectMapMenu;
                    break;
                case 4:
                    currentMenu = mainMenu;
                    break;
            }
        }

        // Call when skirmish menu select event
        public void SkirmishMenuSelect(int choice)
        {
            switch (choice)
            {
                case 0:                   
                    switch (selectMapMenu.ChosenMap)
                    {
                        case 0:
                            gameState = GameState.Play;
                            battleGame.NewSkirmishGame(Content, Window, "Icypaths", skirmishMenu.SkirmishSetup);
                            break;
                        case 1:
                            gameState = GameState.Play;
                            battleGame.NewSkirmishGame(Content, Window, "Frozenfields", skirmishMenu.SkirmishSetup);
                            break;
                        case 2:
                            gameState = GameState.Play;
                            battleGame.NewSkirmishGame(Content, Window, "Crossroads", skirmishMenu.SkirmishSetup);
                            break;
                    } 
                    break;
                case 1:
                    currentMenu = selectMapMenu;
                    break;
            }
        }

        // Call when setting menu select event
        public void SettingMenuSelect(int choice)
        {
            switch (choice)
            {
                // User choose Apply
                case 0:
                    GameSettingSetup newGameSettingSetup = settingMenu.GameSettingSetup;
                    bool isEqual = newGameSettingSetup.Equals(gameSettingSetup);
                    if (!isEqual)
                    {
                        bool isEqualResolution = newGameSettingSetup.ScreenResolution.Equals(gameSettingSetup.ScreenResolution);
                        bool isEqualFull = newGameSettingSetup.IsFullScreen.Equals(gameSettingSetup.IsFullScreen);
                        if (!isEqualFull || !isEqualResolution)
                        {
                            gameSettingSetup.ScreenResolution = newGameSettingSetup.ScreenResolution;
                            gameSettingSetup.IsFullScreen = newGameSettingSetup.IsFullScreen;
                            switch (newGameSettingSetup.ScreenResolution)
                            { 
                                case ScreenResolution.sr1366x768:
                                    InitGraphicsMode(1366, 768, false);
                                    InitGraphicsMode(1366, 768, newGameSettingSetup.IsFullScreen);
                                    break;
                                case ScreenResolution.sr1024x600:
                                    InitGraphicsMode(1024, 600, false);
                                    InitGraphicsMode(1024, 600, newGameSettingSetup.IsFullScreen);
                                    break;
                                case ScreenResolution.sr800x600:
                                    InitGraphicsMode(800, 600, false);
                                    InitGraphicsMode(800, 600, newGameSettingSetup.IsFullScreen);
                                    break;
                            }
                        }
                        bool isEqualMouse = newGameSettingSetup.MouseSpeed.Equals(gameSettingSetup.MouseSpeed);
                        if (!isEqualMouse)
                        {
                            // Proccess when mouse speed change
                            gameSettingSetup.MouseSpeed = newGameSettingSetup.MouseSpeed;
                            switch (newGameSettingSetup.MouseSpeed)
                            {
                                
                            }
                        }
                        bool isEqualMusic = newGameSettingSetup.MusicVolume.Equals(gameSettingSetup.MusicVolume);
                        if (!isEqualMusic)
                        {
                            // Proccess when music volume change
                            gameSettingSetup.MusicVolume = newGameSettingSetup.MusicVolume;
                            switch (newGameSettingSetup.MusicVolume)
                            {
                                case MusicVolume.Low:
                                    Volume.MyVolume = 0.25f;
                                    break;
                                case MusicVolume.Medium:
                                    Volume.MyVolume = 0.5f;
                                    break;
                                case MusicVolume.High:
                                    Volume.MyVolume = 1.0f;
                                    break;
                            }
                            mainMenu.GameMusic.PlaySong(Volume.MyVolume);
                        }
                        bool isEqualVoice = newGameSettingSetup.VoiceVolume.Equals(gameSettingSetup.VoiceVolume);
                        if (!isEqualVoice)
                        {
                            // Proccess when voice volume change
                            gameSettingSetup.VoiceVolume = newGameSettingSetup.VoiceVolume;
                            switch (newGameSettingSetup.VoiceVolume)
                            {
                                
                            }
                        }
                    }
                    mainMenu.UpdateMenuSize(graphics.GraphicsDevice);
                    settingMenu.UpdateMenuSize(graphics.GraphicsDevice);
                    playMenu.UpdateMenuSize(graphics.GraphicsDevice);
                    if (skirmishMenu!=null) skirmishMenu.UpdateMenuSize(graphics.GraphicsDevice);
                    selectMapMenu.UpdateMenuSize(graphics.GraphicsDevice);
                    break;
                // User choose Back
                case 1:
                    currentMenu = mainMenu;
                    break;
            }
        }

        // Call when select map menu select event
        public void SelectMapMenuSelect()
        {
            currentMenu = playMenu;
        }

        // Call when map was select
        public void SelectMap(int numNation)
        {

            skirmishMenu = new SkirmishMenu(Window, Content, GraphicsDevice, "XML/SkirmishMenuWithXML", numNation);
            skirmishMenu.MenuSelect += new SkirmishMenu.EventHandleMenuSelect(SkirmishMenuSelect);
            currentMenu = skirmishMenu;
        }

        // Call when receive back to main menu
        public void EventBackMainMenu()
        {
            gameState = GameState.Menu;
            currentMenu = mainMenu;
            
        }

        // Call when receive exit game
        public void EventExitGame()
        {
            Exit();
        }

        private bool InitGraphicsMode(int iWidth, int iHeight, bool bFullScreen)
        {
            // If we aren't using a full screen mode, the height and width of the window can
            // be set to anything equal to or smaller than the actual screen size.
            if (bFullScreen == false)
            {
                if ((iWidth <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width)
                    && (iHeight <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height))
                {
                    graphics.PreferredBackBufferWidth = iWidth;
                    graphics.PreferredBackBufferHeight = iHeight;
                    graphics.IsFullScreen = bFullScreen;
                    graphics.ApplyChanges();
                    return true;
                }
            }
            else
            {
                // If we are using full screen mode, we should check to make sure that the display
                // adapter can handle the video mode we are trying to set.  To do this, we will
                // iterate thorugh the display modes supported by the adapter and check them against
                // the mode we want to set.
                //foreach (DisplayMode dm in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
                //{
                //    // Check the width and height of each mode against the passed values
                //    if ((dm.Width == iWidth) && (dm.Height == iHeight))
                //    {
                        // The mode is supported, so set the buffer formats, apply changes and return
                        //graphics.PreferredBackBufferWidth = iWidth;
                        //graphics.PreferredBackBufferHeight = iHeight;
                        graphics.IsFullScreen = bFullScreen;
                        graphics.ApplyChanges();
                        return true;
                //    }
                //}
            }
            return false;
        }

    }
}
